using Microsoft.EntityFrameworkCore;
using SheLife.Domain.Entities;
using SheLife.Infrastructure.Data;

namespace SheLife.Infrastructure.Repositories
{
    /// <summary>
    /// 衣物仓储实现
    /// </summary>
    public class ClothingRepository : Repository<Clothing>, IClothingRepository
    {
        public ClothingRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<Clothing>> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet.Where(c => c.UserId == userId).OrderByDescending(c => c.CreatedAt).ToListAsync();
        }

        public async Task<IEnumerable<Clothing>> GetByUserIdAndCategoryAsync(Guid userId, string category)
        {
            return await _dbSet.Where(c => c.UserId == userId && c.Category == category).ToListAsync();
        }

        public async Task<IEnumerable<Clothing>> GetByUserIdAndColorAsync(Guid userId, string color)
        {
            return await _dbSet.Where(c => c.UserId == userId && c.Color == color).ToListAsync();
        }

        public async Task<IEnumerable<Clothing>> GetByUserIdAndSeasonAsync(Guid userId, string season)
        {
            return await _dbSet.Where(c => c.UserId == userId && c.Season == season).ToListAsync();
        }

        public async Task<IEnumerable<Clothing>> GetByUserIdAndStyleAsync(Guid userId, string style)
        {
            return await _dbSet.Where(c => c.UserId == userId && c.Style == style).ToListAsync();
        }

        public async Task<IEnumerable<Clothing>> GetByUserIdAndStatusAsync(Guid userId, string status)
        {
            return await _dbSet.Where(c => c.UserId == userId && c.Status == status).ToListAsync();
        }

        public async Task<Dictionary<string, int>> GetCategoryStatisticsAsync(Guid userId)
        {
            var clothings = await _dbSet
                .Where(c => c.UserId == userId)
                .GroupBy(c => c.Category)
                .Select(g => new { Category = g.Key, Count = g.Count() })
                .ToListAsync();

            return clothings.ToDictionary(c => c.Category, c => c.Count);
        }

        public async Task<Dictionary<string, int>> GetColorStatisticsAsync(Guid userId)
        {
            var clothings = await _dbSet
                .Where(c => c.UserId == userId)
                .GroupBy(c => c.Color)
                .Select(g => new { Color = g.Key, Count = g.Count() })
                .ToListAsync();

            return clothings.ToDictionary(c => c.Color, c => c.Count);
        }

        public async Task<Dictionary<string, int>> GetSeasonStatisticsAsync(Guid userId)
        {
            var clothings = await _dbSet
                .Where(c => c.UserId == userId)
                .GroupBy(c => c.Season)
                .Select(g => new { Season = g.Key, Count = g.Count() })
                .ToListAsync();

            return clothings.ToDictionary(c => c.Season, c => c.Count);
        }

        public async Task<IEnumerable<Clothing>> GetFavoritesAsync(Guid userId)
        {
            return await _dbSet.Where(c => c.UserId == userId && c.IsFavorite).ToListAsync();
        }

        public async Task<IEnumerable<Clothing>> GetRecentlyWornAsync(Guid userId, int days = 30)
        {
            var thresholdDate = DateTime.UtcNow.AddDays(-days);
            return await _dbSet.Where(c => c.UserId == userId && c.LastWornDate >= thresholdDate).ToListAsync();
        }
    }

    /// <summary>
    /// 搭配仓储实现
    /// </summary>
    public class OutfitRepository : Repository<Outfit>, IOutfitRepository
    {
        public OutfitRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<Outfit>> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet.Where(o => o.UserId == userId).OrderByDescending(o => o.CreatedAt).ToListAsync();
        }

        public async Task<IEnumerable<Outfit>> GetByUserIdAndSeasonAsync(Guid userId, string season)
        {
            return await _dbSet.Where(o => o.UserId == userId && o.Season == season).ToListAsync();
        }

        public async Task<IEnumerable<Outfit>> GetByUserIdAndOccasionAsync(Guid userId, string occasion)
        {
            return await _dbSet.Where(o => o.UserId == userId && o.Occasion == occasion).ToListAsync();
        }

        public async Task<IEnumerable<Outfit>> GetByUserIdAndStyleAsync(Guid userId, string style)
        {
            return await _dbSet.Where(o => o.UserId == userId && o.Style == style).ToListAsync();
        }

        public async Task<IEnumerable<Outfit>> GetFavoritesAsync(Guid userId)
        {
            return await _dbSet.Where(o => o.UserId == userId && o.IsFavorite).ToListAsync();
        }

        public async Task<Outfit?> GetByUserIdAndDateAsync(Guid userId, DateTime date)
        {
            return await _dbSet.FirstOrDefaultAsync(o => o.UserId == userId && o.WornDate.HasValue && o.WornDate.Value.Date == date.Date);
        }

        public async Task<Dictionary<string, int>> GetSeasonStatisticsAsync(Guid userId)
        {
            var outfits = await _dbSet
                .Where(o => o.UserId == userId)
                .GroupBy(o => o.Season)
                .Select(g => new { Season = g.Key, Count = g.Count() })
                .ToListAsync();

            return outfits.ToDictionary(o => o.Season, o => o.Count);
        }

        public async Task<Dictionary<string, int>> GetOccasionStatisticsAsync(Guid userId)
        {
            var outfits = await _dbSet
                .Where(o => o.UserId == userId)
                .GroupBy(o => o.Occasion)
                .Select(g => new { Occasion = g.Key, Count = g.Count() })
                .ToListAsync();

            return outfits.ToDictionary(o => o.Occasion, o => o.Count);
        }

        public async Task<IEnumerable<Outfit>> GetRecentlyWornAsync(Guid userId, int days = 30)
        {
            var thresholdDate = DateTime.UtcNow.AddDays(-days);
            return await _dbSet.Where(o => o.UserId == userId && o.WornDate.HasValue && o.WornDate.Value >= thresholdDate).ToListAsync();
        }
    }

    /// <summary>
    /// 搭配衣物仓储实现
    /// </summary>
    public class OutfitClothingRepository : Repository<OutfitClothing>, IOutfitClothingRepository
    {
        public OutfitClothingRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<OutfitClothing>> GetByOutfitIdAsync(Guid outfitId)
        {
            return await _dbSet.Where(oc => oc.OutfitId == outfitId).ToListAsync();
        }

        public async Task<IEnumerable<OutfitClothing>> GetByClothingIdAsync(Guid clothingId)
        {
            return await _dbSet.Where(oc => oc.ClothingId == clothingId).ToListAsync();
        }

        public async Task<Dictionary<Guid, List<OutfitClothing>>> GetByOutfitIdsAsync(IEnumerable<Guid> outfitIds)
        {
            var items = await _dbSet.Where(oc => outfitIds.Contains(oc.OutfitId)).ToListAsync();
            
            return items
                .GroupBy(oc => oc.OutfitId)
                .ToDictionary(g => g.Key, g => g.ToList());
        }

        public async Task<Dictionary<Guid, int>> GetClothingUsageCountAsync(Guid userId, int days = 30)
        {
            var endDate = DateTime.UtcNow;
            var startDate = endDate.AddDays(-days);

            var outfitIds = await _context.Set<Outfit>()
                .Where(o => o.UserId == userId && o.WornDate.HasValue && o.WornDate.Value >= startDate && o.WornDate.Value <= endDate)
                .Select(o => o.Id)
                .ToListAsync();

            var items = await _dbSet
                .Where(oc => outfitIds.Contains(oc.OutfitId))
                .GroupBy(oc => oc.ClothingId)
                .Select(g => new { ClothingId = g.Key, Count = g.Count() })
                .ToListAsync();

            return items.ToDictionary(i => i.ClothingId, i => i.Count);
        }
    }

    /// <summary>
    /// 搭配记录仓储实现
    /// </summary>
    public class OutfitRecordRepository : Repository<OutfitRecord>, IOutfitRecordRepository
    {
        public OutfitRecordRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<OutfitRecord>> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet.Where(r => r.UserId == userId).OrderByDescending(r => r.WornDate).ToListAsync();
        }

        public async Task<IEnumerable<OutfitRecord>> GetByUserIdAndDateRangeAsync(Guid userId, DateTime startDate, DateTime endDate)
        {
            return await _dbSet.Where(r => r.UserId == userId && r.WornDate >= startDate && r.WornDate <= endDate).ToListAsync();
        }

        public async Task<OutfitRecord?> GetByUserIdAndDateAsync(Guid userId, DateTime date)
        {
            return await _dbSet.FirstOrDefaultAsync(r => r.UserId == userId && r.WornDate.Date == date.Date);
        }

        public async Task<IEnumerable<OutfitRecord>> GetByOutfitIdAsync(Guid outfitId)
        {
            return await _dbSet.Where(r => r.OutfitId == outfitId).OrderByDescending(r => r.WornDate).ToListAsync();
        }

        public async Task<Dictionary<DateTime, int>> GetDailyOutfitCountAsync(Guid userId, int days = 30)
        {
            var endDate = DateTime.UtcNow.Date;
            var startDate = endDate.AddDays(-days);

            var records = await _dbSet
                .Where(r => r.UserId == userId && r.WornDate >= startDate && r.WornDate <= endDate)
                .ToListAsync();

            var result = new Dictionary<DateTime, int>();
            for (var date = startDate; date <= endDate; date = date.AddDays(1))
            {
                var dayRecords = records.Where(r => r.WornDate.Date == date.Date);
                result[date] = dayRecords.Count();
            }

            return result;
        }

        public async Task<Dictionary<string, int>> GetOccasionStatisticsAsync(Guid userId, int days = 30)
        {
            var endDate = DateTime.UtcNow;
            var startDate = endDate.AddDays(-days);

            var records = await _dbSet
                .Where(r => r.UserId == userId && r.WornDate >= startDate && r.WornDate <= endDate)
                .ToListAsync();

            var outfitIds = records.Select(r => r.OutfitId).Distinct().ToList();

            var outfits = await _context.Set<Outfit>()
                .Where(o => outfitIds.Contains(o.Id))
                .ToListAsync();

            var result = new Dictionary<string, int>();
            foreach (var record in records)
            {
                var outfit = outfits.FirstOrDefault(o => o.Id == record.OutfitId);
                if (outfit != null)
                {
                    if (result.ContainsKey(outfit.Occasion))
                        result[outfit.Occasion]++;
                    else
                        result[outfit.Occasion] = 1;
                }
            }

            return result;
        }
    }

    /// <summary>
    /// 搭配模板仓储实现
    /// </summary>
    public class OutfitTemplateRepository : Repository<OutfitTemplate>, IOutfitTemplateRepository
    {
        public OutfitTemplateRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<OutfitTemplate>> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet.Where(t => t.UserId == userId).OrderByDescending(t => t.CreatedAt).ToListAsync();
        }

        public async Task<IEnumerable<OutfitTemplate>> GetByUserIdAndSeasonAsync(Guid userId, string season)
        {
            return await _dbSet.Where(t => t.UserId == userId && t.Season == season).ToListAsync();
        }

        public async Task<IEnumerable<OutfitTemplate>> GetByUserIdAndOccasionAsync(Guid userId, string occasion)
        {
            return await _dbSet.Where(t => t.UserId == userId && t.Occasion == occasion).ToListAsync();
        }

        public async Task<IEnumerable<OutfitTemplate>> GetByUserIdAndStyleAsync(Guid userId, string style)
        {
            return await _dbSet.Where(t => t.UserId == userId && t.Style == style).ToListAsync();
        }

        public async Task<IEnumerable<OutfitTemplate>> GetByLifeStageAsync(string lifeStage)
        {
            return await _dbSet.Where(t => t.LifeStage == lifeStage || t.LifeStage == "all").ToListAsync();
        }

        public async Task<IEnumerable<OutfitTemplate>> GetPublicTemplatesAsync()
        {
            return await _dbSet.Where(t => t.IsPublic).OrderByDescending(t => t.CreatedAt).ToListAsync();
        }

        public async Task<Dictionary<string, int>> GetSeasonStatisticsAsync(Guid userId)
        {
            var templates = await _dbSet
                .Where(t => t.UserId == userId)
                .GroupBy(t => t.Season)
                .Select(g => new { Season = g.Key, Count = g.Count() })
                .ToListAsync();

            return templates.ToDictionary(t => t.Season, t => t.Count);
        }

        public async Task<Dictionary<string, int>> GetOccasionStatisticsAsync(Guid userId)
        {
            var templates = await _dbSet
                .Where(t => t.UserId == userId)
                .GroupBy(t => t.Occasion)
                .Select(g => new { Occasion = g.Key, Count = g.Count() })
                .ToListAsync();

            return templates.ToDictionary(t => t.Occasion, t => t.Count);
        }
    }

    /// <summary>
    /// 搭配模板项仓储实现
    /// </summary>
    public class OutfitTemplateItemRepository : Repository<OutfitTemplateItem>, IOutfitTemplateItemRepository
    {
        public OutfitTemplateItemRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<OutfitTemplateItem>> GetByTemplateIdAsync(Guid templateId)
        {
            return await _dbSet.Where(i => i.TemplateId == templateId).ToListAsync();
        }

        public async Task<IEnumerable<OutfitTemplateItem>> GetByCategoryAsync(Guid templateId, string category)
        {
            return await _dbSet.Where(i => i.TemplateId == templateId && i.Category == category).ToListAsync();
        }

        public async Task<Dictionary<Guid, List<OutfitTemplateItem>>> GetByTemplateIdsAsync(IEnumerable<Guid> templateIds)
        {
            var items = await _dbSet.Where(i => templateIds.Contains(i.TemplateId)).ToListAsync();
            
            return items
                .GroupBy(i => i.TemplateId)
                .ToDictionary(g => g.Key, g => g.ToList());
        }

        public async Task<Dictionary<string, List<OutfitTemplateItem>>> GetByCategoryAsync(Guid templateId)
        {
            var items = await _dbSet.Where(i => i.TemplateId == templateId).ToListAsync();
            
            return items
                .GroupBy(i => i.Category)
                .ToDictionary(g => g.Key, g => g.ToList());
        }
    }

    /// <summary>
    /// 用户搭配模板仓储实现
    /// </summary>
    public class UserOutfitTemplateRepository : Repository<UserOutfitTemplate>, IUserOutfitTemplateRepository
    {
        public UserOutfitTemplateRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<UserOutfitTemplate>> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet.Where(ut => ut.UserId == userId).OrderByDescending(ut => ut.CreatedAt).ToListAsync();
        }

        public async Task<IEnumerable<UserOutfitTemplate>> GetByUserIdAndTemplateIdAsync(Guid userId, Guid templateId)
        {
            return await _dbSet.Where(ut => ut.UserId == userId && ut.TemplateId == templateId).ToListAsync();
        }

        public async Task<UserOutfitTemplate?> GetByUserIdAndTemplateIdAsync(Guid userId, Guid templateId)
        {
            return await _dbSet.FirstOrDefaultAsync(ut => ut.UserId == userId && ut.TemplateId == templateId);
        }

        public async Task<IEnumerable<UserOutfitTemplate>> GetByTemplateIdAsync(Guid templateId)
        {
            return await _dbSet.Where(ut => ut.TemplateId == templateId).ToListAsync();
        }

        public async Task<Dictionary<Guid, int>> GetTemplateUsageCountAsync(int days = 30)
        {
            var endDate = DateTime.UtcNow;
            var startDate = endDate.AddDays(-days);

            var templates = await _dbSet
                .Where(ut => ut.CreatedAt >= startDate && ut.CreatedAt <= endDate)
                .GroupBy(ut => ut.TemplateId)
                .Select(g => new { TemplateId = g.Key, Count = g.Count() })
                .ToListAsync();

            return templates.ToDictionary(t => t.TemplateId, t => t.Count);
        }
    }

    /// <summary>
    /// 搭配建议仓储实现
    /// </summary>
    public class OutfitSuggestionRepository : Repository<OutfitSuggestion>, IOutfitSuggestionRepository
    {
        public OutfitSuggestionRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<OutfitSuggestion>> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet.Where(s => s.UserId == userId).OrderByDescending(s => s.CreatedAt).ToListAsync();
        }

        public async Task<IEnumerable<OutfitSuggestion>> GetByUserIdAndDateRangeAsync(Guid userId, DateTime startDate, DateTime endDate)
        {
            return await _dbSet.Where(s => s.UserId == userId && s.CreatedAt >= startDate && s.CreatedAt <= endDate).ToListAsync();
        }

        public async Task<IEnumerable<OutfitSuggestion>> GetByUserIdAndSeasonAsync(Guid userId, string season)
        {
            return await _dbSet.Where(s => s.UserId == userId && s.Season == season).ToListAsync();
        }

        public async Task<IEnumerable<OutfitSuggestion>> GetByUserIdAndOccasionAsync(Guid userId, string occasion)
        {
            return await _dbSet.Where(s => s.UserId == userId && s.Occasion == occasion).ToListAsync();
        }

        public async Task<IEnumerable<OutfitSuggestion>> GetByLifeStageAsync(string lifeStage)
        {
            return await _dbSet.Where(s => s.LifeStage == lifeStage || s.LifeStage == "all").ToListAsync();
        }

        public async Task<OutfitSuggestion?> GetLatestByUserIdAsync(Guid userId)
        {
            return await _dbSet.Where(s => s.UserId == userId).OrderByDescending(s => s.CreatedAt).FirstOrDefaultAsync();
        }

        public async Task<Dictionary<string, int>> GetSeasonStatisticsAsync(Guid userId)
        {
            var suggestions = await _dbSet
                .Where(s => s.UserId == userId)
                .GroupBy(s => s.Season)
                .Select(g => new { Season = g.Key, Count = g.Count() })
                .ToListAsync();

            return suggestions.ToDictionary(s => s.Season, s => s.Count);
        }

        public async Task<Dictionary<string, int>> GetOccasionStatisticsAsync(Guid userId)
        {
            var suggestions = await _dbSet
                .Where(s => s.UserId == userId)
                .GroupBy(s => s.Occasion)
                .Select(g => new { Occasion = g.Key, Count = g.Count() })
                .ToListAsync();

            return suggestions.ToDictionary(s => s.Occasion, s => s.Count);
        }
    }
}